package com.java.shop.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.common.utils.PageUtils;
import com.java.common.utils.Query;
import com.java.shop.product.dao.CategoryDao;
import com.java.shop.product.entity.CategoryBrandRelationEntity;
import com.java.shop.product.entity.CategoryEntity;
import com.java.shop.product.service.CategoryBrandRelationService;
import com.java.shop.product.service.CategoryService;
import com.java.shop.product.webvo.Catelog2Vo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @CacheEvict(value = {"category"},allEntries = true)
    @Transactional
    @Override
    public void updateDetail(CategoryEntity category) {
        this.updateById(category);
        //判断是否在关联分类表中有数据
        Integer catelogRelationCount = categoryBrandRelationService.count(new QueryWrapper<CategoryBrandRelationEntity>().eq("brand_id",category.getCatId()));
        if(catelogRelationCount == 0) return;
        if(!StringUtils.isEmpty(category.getName())){
            QueryWrapper<CategoryBrandRelationEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("catelog_id",category.getCatId());
            CategoryBrandRelationEntity categoryBrandRelationEntity = new CategoryBrandRelationEntity();
            categoryBrandRelationEntity.setBrandName(category.getName());
            categoryBrandRelationService.update(categoryBrandRelationEntity,wrapper);
            //TODO 关联其他有含有category字段表的数据
        }
    }

    @Override
    public List<Long> getParentIds(Long categoryId) {
        List<Long> parentIds = getParentIds(new ArrayList<Long>(), categoryId);
        if(parentIds.size() > 0) Collections.reverse(parentIds);
        return parentIds;
    }

    public List<Long> getParentIds(List<Long> list, Long categoryId) {
        list.add(categoryId);
        CategoryEntity entity = this.getById(categoryId);
        if(entity != null && entity.getParentCid() != null && entity.getParentCid() != 0L){
            getParentIds(list,entity.getParentCid());
        }
        return list;
    }




    @Override
    public List<CategoryEntity> listWithTree() {
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        return categoryTree(categoryEntities, 0L);
    }


    /**
     * 递归返回树形结构
     *
     * 第一次使用filter过滤掉不是一级分类的，设置一级分类的children，递归
     * @param allData
     * @param pid
     * @return
     */
    private static List<CategoryEntity> categoryTree(List<CategoryEntity> allData, Long pid){
        return allData.stream()
                .filter(item-> pid.equals(item.getParentCid()))
                .map(item->{
                    item.setChildren(categoryTree(allData,item.getCatId()));
                    return item;
                })
                .sorted((m1,m2)->{
                    return (m1.getSort()==null ? 0 : m1.getSort()) - (m2.getSort() == null ? 0: m2.getSort());
                })
                .collect(Collectors.toList());
    }


    /**
     * 查询一级分类
     * @return
     */
    @Cacheable(value = {"category"}, key = "#root.methodName")
    @Override
    public List<CategoryEntity> getCatelog1() {
        List<CategoryEntity> list = this.list();
        System.out.println("getCatelog1查了数据库。。。");
        return list.stream().filter(item->item.getParentCid()==0).collect(Collectors.toList());
    }

    /**
     * 通过一级分类查询到子分类
     * @return
     */
    @Cacheable(value = {"category"}, key = "#root.method.name")
    @Override
    public Map<String, List<Catelog2Vo>> getCatalogJson() {
        return getRedisCatalogJson();
    }

    public Map<String, List<Catelog2Vo>> getRedisCatalogJson(){
        List<CategoryEntity> catelogAll = this.list();
        System.out.println("getRedisCatalogJson查了数据库。。。");
        List<CategoryEntity> catelog1 = catelogAll.stream().filter(item->item.getParentCid()==0).collect(Collectors.toList());
        Map<String, List<Catelog2Vo>> result = catelog1.stream().collect(Collectors.toMap(cate1->cate1.getCatId().toString(), cate1 -> {
            // 返回List<Catelog2Vo>
            // 查找2级分类
            return catelogAll.stream()
                    .filter(cate -> cate.getParentCid() == cate1.getCatId())
                    .map(cate2 -> {
                        Catelog2Vo catelog2Vo = new Catelog2Vo(cate1.getCatId().toString(), null, cate2.getCatId().toString(), cate2.getName());
                        //查找3级分类
                        List<Catelog2Vo.Catelog3Vo> cate3List = catelogAll.stream()
                                .filter(cate -> cate.getParentCid() == cate2.getCatId())
                                .map(cate3 -> {
                                    return new Catelog2Vo.Catelog3Vo(cate2.getCatId().toString(), cate3.getCatId().toString(), cate3.getName());
                                }).collect(Collectors.toList());

                        catelog2Vo.setCatalog3List(cate3List);
                        return catelog2Vo;
                    })
                    .collect(Collectors.toList());

        }));
        return result;
    }
}